;; midi-bytes.scm - (c) rohan drape, 2002-2005

;; Combine two eight bit bytes (seven bit unsigned integers) into an
;; unsigned integer of at most fourteen bits of precision, ie. in the
;; range 0 to 16384.  Some controller data is encoded in this manner.

(define (midi-combine-bytes a b)
  (bitwise-xor a (arithmetic-shift b 7)))

;; Uncombine the integer `z' (a fourteen bit unsigned integer) into
;; two eight bit bytes (seven bit unsigned integers).  This is the
;; inverse of the 'midi-combine-bytes' operation.

(define (midi-uncombine-value z)
  (list (bitwise-and #x7F z)
	(bitwise-and #xFF (arithmetic-shift z -7))))

;; Combine the major and minor parts of a status byte.  Typically the
;; major is the message type, the minor the channel number.  This is
;; simply a bitwise eXclusive OR operation.

(define (midi-status-byte-construct major minor)
  (bitwise-xor major minor))

(define (midi-status-minor s)
  (bitwise-and s #x0F))

(define (midi-status-major s)
  (bitwise-and s #xF0))

;; Evaluates to the list of the `n' bytes encoding the integer `z'.
;; Midi sends and store the most significant byte first.  Legal values
;; for `n' are one, two, three and four.  This procedure raises an
;; error if it is not possible to encode `z' in `n' bytes.

(define (midi-integer-to-byte-list z n)
  (case n
    ((1) (if (>= z 256)
	     (error "midi-integer-to-byte-list: Integer out of range" z n)
	     (list (bitwise-and #xFF z))))
    ((2) (if (>= z 65536)
	     (error "midi-integer-to-byte-list: Integer out of range" z n)
	     (list (bitwise-and #xFF (arithmetic-shift z -8))
		   (bitwise-and #xFF z))))
    ((3) (if (>= z 16777216)
	     (error "midi-integer-to-byte-list: Integer out of range" z n)
	     (list (bitwise-and #xFF (arithmetic-shift z -16))
		   (bitwise-and #xFF (arithmetic-shift z -8))
		   (bitwise-and #xFF z))))
    ((4) (if (>= z 4294967296)
	     (error "midi-integer-to-byte-list: Integer out of range" z n)
	     (list (bitwise-and #xFF (arithmetic-shift z -24))
		   (bitwise-and #xFF (arithmetic-shift z -16))
		   (bitwise-and #xFF (arithmetic-shift z -8))
		   (bitwise-and #xFF z))))
    (else (error "midi-integer-to-byte-list: Illegal byte count"))))

;; Evalutes to '#t' iff `data' is a status byte of `type'.

(define (midi-status-check type data)
  (= (bitwise-and type data) type))

